
//--> Loth 2011 
//--> Full car simulator based on muzer's script

package chamans.away
{
	//import chamans.*
	import flash.display.*;
	import flash.events.*;
	import flash.geom.*;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.net.*;
	import flash.ui.*;
	import flash.utils.*;	
	
	import away3d.materials.methods.*;
	import away3d.primitives.*;
	import away3d.containers.*;
	import away3d.materials.*;
	import away3d.core.base.*;
	import away3d.entities.*;
	import away3d.events.*;
	
	import jiglib.math.*;	
	import jiglib.vehicles.*;
	import jiglib.plugin.away3d4.*;

	
	public class c1gt
	{
		// SOUND
		/*[Embed(source="assets/startup.mp3")]
		public var SoundStart:Class;
		[Embed(source="assets/viper2.mp3")]
		public var SoundEngine:Class;
		private var CARSOUND:CarSound */
		
		private var firstestart:Boolean=false;
		public var carGhost:Cube;
		public var meshListe:Vector.<Mesh> ;
		public var container:ObjectContainer3D;
		public var carok:Boolean=false;
		
		private var speed:Number=0;
		private var Wid:Array=["WheelFL", "WheelFR", "WheelBL", "WheelBR"];
		private var i:int;
		private var END:Function;
		private var ech:Number=2.54;
		private var follow:Boolean=true;
		private var O:Object;
		private var carBody:JCar;
		private var matListe:Vector.<BitmapMaterial> ;
		private var carBuild:Boolean=false;
		private var MapListe:Array;
		private var MovieListe:Array;
		private var Dleft:Boolean=false;
		private var Dright:Boolean=false;
		//___________________________________all setting for car 
		public var cardata:Object = {
			    Friction:.5, Restitution:.2, mass:10,
			    WRadius:17*ech, Wheight:14*ech, Wposy:-4*ech, decy:21*ech,
				W: 90*ech,  D:160*ech,   H: 30*ech, 
				AX:59.5*ech,  AX2:-59.5*ech,  AY:-10*ech,  AZ:39*ech,
				maxSteerAngle: 40, steerRate:.25,  driveTorque:1600,
				
				SideFriction:1,  FwdFriction:1.2,  Travel:4, 
				Resting: .5,  Damping: .2, NumRays:3, 
				Collision:true
		}
		
		public function c1gt(o:Object, end:Function=null):void
		{
			O=o;
			END=end
			var mat:ColorMaterial = new ColorMaterial(0x3399FF, .2);
			with(cardata){ carGhost=new Cube(mat, W, H, D);carGhost.castsShadows = false;}	
			//________________________________________load swf map
			O.LOAD.SWF("assets/c1gt/c1gt.swf", [ 'BODY', "BODYdoor", "WHEEL", "INTERN", "STEERING", "CARLIGHT" ], INIT)
			
			//var S1:Sound= new SoundEngine() as Sound
			//var S2:Sound=new SoundStart() as Sound
			//CARSOUND=new CarSound( S1, S2)
		}
		private function INIT( A:Array ) : void
		{
			MovieListe=A
			O.LOAD.IMGLIST("assets/c1gt/", ['carw_normal', "car_normal", "portenormal" ], INIT2 , ".jpg")
		}
		private function INIT2( A:Array ) : void
		{
			MapListe=A
			meshListe = new Vector.<Mesh>();
			O.OBJ3D('assets/c1gt/c1gt.obj', Display_Car)
			O.stage.addEventListener( KeyboardEvent.KEY_DOWN, keyDownHandler );
			O.stage.addEventListener( KeyboardEvent.KEY_UP, keyUpHandler );
		}
		private function Display_Car(obj:ObjectContainer3D) : void
		{
			container=obj;
			O.view.scene.addChild(container);
			matListe=new Vector.<BitmapMaterial>
			//  0-4  // wheel_1, wheel_2, wheel_3, wheel_4, volent,
			//  5-9  // internbody, body,  door_l, door_r, light,
			// 10-14 // hood, window, trunk, door_window_l, door_window_r 
			var midmap:Boolean=true;
			var quality:Number=1 // can be .25, .5, 1, 2
			var matHiden:ColorMaterial=new ColorMaterial(0xFF, 0)
			var tmp01:BitmapData=O.TOOL.bit(new MovieListe[0](), 1024,1024,quality,false);
			var matBody:BitmapMaterial = new BitmapMaterial(tmp01, true, false, midmap );
			var matBodyDoor:BitmapMaterial = new BitmapMaterial(O.TOOL.bit(new MovieListe[1](), 1024,1024,quality,false), true, false, midmap );
			var matWheel:BitmapMaterial = new BitmapMaterial(O.TOOL.bit(new MovieListe[2](), 512,512,quality,false), true, false, midmap);
			var matIntern:BitmapMaterial = new BitmapMaterial(O.TOOL.bit(new MovieListe[3](), 1024,1024,quality,false), true, false, midmap);
			var matSteering:BitmapMaterial = new BitmapMaterial(O.TOOL.bit(new MovieListe[4](), 256,256,quality,false), true, false, midmap);
			var matLight:BitmapMaterial = new BitmapMaterial(O.TOOL.bit(new MovieListe[5](), 256,256,quality,false), true, false, midmap);
			var matHood:BitmapMaterial =  new BitmapMaterial(tmp01, true, false, midmap );	
			var matWindow:BitmapMaterial = new BitmapMaterial(O.TOOL.bit(new MovieListe[0](), 1024,1024,quality,true), true, false, midmap );
			var matMask:BitmapMaterial =  new BitmapMaterial(tmp01, true, false, midmap );	
			var matGrid:BitmapMaterial = new BitmapMaterial(tmp01, true, false, midmap );	
			
			matListe.push(matBody);
			matListe.push(matBodyDoor);
			matListe.push(matWheel);
			matListe.push(matIntern);
			matListe.push(matSteering);
			matListe.push(matLight);
			matListe.push(matHood);
			matListe.push(matWindow);
			matListe.push(matMask);
			matListe.push(matGrid);
			// refection environement
			matBody.addMethod(new EnvMapMethod(O.SKY.envMap,.3));
			matHood.addMethod(new EnvMapMethod(O.SKY.envMap,.3));
			matBodyDoor.addMethod(new EnvMapMethod(O.SKY.envMap,.3));
			matWindow.addMethod( new EnvMapMethod(O.SKY.envMap,.3));
			//	matLight.addMethod( new EnvMapMethod(O.SKY.envMap,.4));
			//	matWheel.addMethod( new EnvMapMethod(O.SKY.envMap,.05));
			//	matGrid.addMethod( new EnvMapMethod(O.SKY.envMap,.05));
			
			for each(var mat:BitmapMaterial in matListe){
				mat.lights = O.LIGHT;
				mat.ambientColor= O.FogColor;
				mat.ambient = 0.25;
				mat.specular=1.3
				
			}
			
			matWindow.specular =1.5; matWindow.gloss =30
			//	matLight.specular =1.5; matLight.gloss =30
			matGrid.specular =.6; matGrid.gloss =60
			matMask.specular =.6; matMask.gloss =60
			matWheel.specular =.6; matWheel.gloss =60
			matIntern.specular = .5; matIntern.gloss = 60
			matSteering.specular =.5;  matSteering.gloss =60
			
			matWindow.transparent=true 
			matWindow.bothSides=true
			matHood.bothSides=true
			
			// normal map
			matWheel.normalMap=MapListe[0]
			matBody.normalMap=MapListe[1]
			matWindow.normalMap=MapListe[1]
			// matLight.normalMap=MapListe[1]
			matGrid.normalMap=MapListe[1]
			matBodyDoor.normalMap=MapListe[2]
			
			var mesh : Mesh;
			
			for ( var i:int = 0; i < container.numChildren; ++i) {
				mesh = Mesh(container.getChildAt(i));
				mesh.castsShadows=true;
				if( i==5 ){ mesh.material = matBody;}
				else if( i==7 || i==8 ){ mesh.material = matBodyDoor;}
				else if( i==0 || i==1 || i==2 || i==3 ) mesh.material = matWheel
				else if( i==6 ) mesh.material = matIntern;
				else if( i==4 ) mesh.material = matSteering
				else if( i==9 ){ mesh.material = matLight; mesh.castsShadows=false;
				}
				else if( i==10 ) mesh.material = matHood
				else if( i==11 || i==12 || i==13 || i==14 ){ mesh.material = matWindow; //mesh.castsShadows=false;
				}
				else if( i==15 ){ mesh.material = matMask;}
				else if( i==16 ){ mesh.material = matGrid; }
				//else  mesh.material = matHiden
				meshListe.push(mesh)
			}
			// Move Rotation of mesh
			
			with(cardata){
				// body / doors
				meshListe[5].y=meshListe[15].y=meshListe[16].y=meshListe[6].y=meshListe[9].y=meshListe[11].y=decy
				meshListe[5].z=meshListe[15].z=meshListe[16].z=meshListe[6].z=meshListe[9].z=meshListe[11].z=4.5*ech
				// doors & doors windows
				meshListe[7].y=meshListe[8].y=meshListe[13].y=meshListe[14].y=decy+(29*ech)
				meshListe[7].z=meshListe[8].z=meshListe[13].z=meshListe[14].z=2.5*ech
				meshListe[8].x=meshListe[13].x=7.5*ech; 
				meshListe[7].x=meshListe[14].x=-7.5*ech;
				meshListe[7].rotationX=meshListe[8].rotationX=meshListe[13].rotationX=meshListe[14].rotationX=-5
				// Steering
				meshListe[4].rotationX=-210; 
				meshListe[4].x=20*ech;//english one
				meshListe[4].z=28.5*ech;meshListe[4].y=(5*ech)+decy
				// wheels
				meshListe[1].x=meshListe[2].x=AZ
				meshListe[0].x=meshListe[3].x=-AZ
					meshListe[0].rotationZ=meshListe[2].rotationZ=180
				meshListe[0].z=meshListe[1].z=AX
				meshListe[2].z=meshListe[3].z=-AX
					//	hood 
					meshListe[10].z=(55.5*ech)
				meshListe[10].y=decy+(4*ech)
				// trunk
				meshListe[12].y=(19*ech)+decy
				meshListe[12].z=-59.5*ech
			}
			//interactivity door / hood
			/*meshListe[8].mouseEnabled = true;
			meshListe[8].addEventListener(MouseEvent3D.CLICK, door_right);
			meshListe[8].mouseEnabled = true;
			meshListe[7].addEventListener(MouseEvent3D.CLICK, door_left);
			meshListe[7].mouseEnabled = true;
			meshListe[10].addEventListener(MouseEvent3D.CLICK, hood_action);
			meshListe[10].mouseEnabled = true;
			meshListe[12].addEventListener(MouseEvent3D.CLICK, trunk_action);
			meshListe[12].mouseEnabled = true;
			*/
			
			CarSimulation()
		}
		public function hideDoor(b:Boolean=true) : void
		{
			if(b){
				var matHiden:ColorMaterial=new ColorMaterial(0xFF,0)
				meshListe[15].material=matHiden;
			}
			else 
				meshListe[15].material=matListe[8]
		}
		private function CarSimulation():void
		{
			var M:Away3D4Mesh;
			
			with(cardata){
				// carGhost=new Cube(mat, W, H, D) ;
				// O.view.scene.addChild(carGhost);
				M=new Away3D4Mesh(carGhost);
				carBody = new JCar(M);
				O.physics.world.addBody(carBody.chassis);
				
				set_car();
				set_sideLengths();
				car_physics();
				set_wheels();
				car_reset();
				carBuild=true;
				hideDoor();
				if (END!=null)END();
			}
		}
		public function set_wheels(e:Event=null):void
		{
			var posX:Array=[-cardata.AZ, cardata.AZ, -cardata.AZ, cardata.AZ];
			var posZ:Array=[ cardata.AX, cardata.AX, -cardata.AX, -cardata.AX];
			with(cardata){
				for ( i=0; i<4; ++i){
					carBody.setupWheel(Wid[i], new Vector3D(posX[i],Wposy, posZ[i]), SideFriction,FwdFriction,Travel, WRadius, Resting, Damping, NumRays)
				}}
		}
		public function set_car(e:Event=null):void
		{
			carBody.setCar( cardata.maxSteerAngle, cardata.steerRate, cardata.driveTorque )
		}
		public function set_sideLengths(e:Event=null):void
		{
			with(cardata){
				carBody.chassis.sideLengths = new Vector3D(W, H, D);
			}}
		public function car_physics(e:Event=null):void
		{
			carBody.chassis.mass = cardata.mass;
			carBody.chassis.friction = cardata.Friction;
			carBody.chassis.restitution = cardata.Restitution;
		}
		private function car_reset(e:Event=null):void
		{
			carBody.chassis.moveTo(new Vector3D(0, 400,0));
			carBody.chassis.rotationX=0
			carBody.chassis.rotationY=0
			carBody.chassis.rotationZ=0	
			//O.view.camera.target=carGhost
		}
		
		private function keyDownHandler(event :KeyboardEvent):void
		{
			//if (!firstestart){firstestart=true; CARSOUND.start() }
			switch(event.keyCode)
			{
				case Keyboard.UP:
					speed+=10;
					carBody.setAccelerate(1);
					break;
				case Keyboard.DOWN:
					speed-=10;
					carBody.setAccelerate(-1);
					break;
				case Keyboard.LEFT:
					carBody.setSteer(["WheelFL", "WheelFR"], -1);
					meshListe[4].roll(-10);
					break;
				case Keyboard.RIGHT:
					carBody.setSteer(["WheelFL", "WheelFR"], 1);
					meshListe[4].roll(10);
					break;
				case Keyboard.SPACE:
					carBody.setHBrake(1);
					break;
				case Keyboard.ENTER:
					car_reset()
					break;
			}
		}
		
		private function keyUpHandler(event:KeyboardEvent):void
		{
			switch(event.keyCode)
			{
				case Keyboard.UP:
					
					carBody.setAccelerate(0);
					speed=0
					break;
				
				case Keyboard.DOWN:
					carBody.setAccelerate(0);
					speed=0
					break;
				
				case Keyboard.LEFT:
					carBody.setSteer(["WheelFL", "WheelFR"], 0);
					break;
				
				case Keyboard.RIGHT:
					carBody.setSteer(["WheelFL", "WheelFR"], 0);
					break;
				case Keyboard.SPACE:
					carBody.setHBrake(0);
			}
		}
		///////////////////////////////////
		//        UPDATE CAR             //
		///////////////////////////////////
		public function update():void
		{
			if (!carBuild) return;
			container.transform= carGhost.transform
			//CARSOUND.rate =(carBody.wheels[Wid[0]].getRollAngle()>>0) * 30;
			for( var i:int=0; i<4; ++i){
				if(i==1) {
					meshListe[(i)].rotationX -= carBody.wheels[Wid[i]].getRollAngle()
					meshListe[(i)].rotationY = carBody.wheels[Wid[i]].getSteerAngle()
				}
				else if(i==0){  
					meshListe[(i)].rotationX += carBody.wheels[Wid[i]].getRollAngle()
					meshListe[(i)].rotationY = -carBody.wheels[Wid[i]].getSteerAngle()
				}
				else{   
					if(i==2)meshListe[(i)].rotationX += carBody.wheels[Wid[i]].getRollAngle()
					else meshListe[(i)].rotationX -= carBody.wheels[Wid[i]].getRollAngle()
				}
				meshListe[(i)].y=carBody.wheels[Wid[i]].getActualPos().y
				if(carBody.chassis.y<-2000)car_reset()	
			}
			
		}
		
		///////////////////////////// Hood & Doors MouseEvent3D Interactivity
		public function trunk_action(e:MouseEvent3D):void // coffre arriere
		{
			if(meshListe[12].rotationX==0)	O.stage.addEventListener(Event.ENTER_FRAME, openTrunk, false, 0, true);
			else O.stage.addEventListener(Event.ENTER_FRAME, closeTrunk, false, 0, true);
		}
		public function hood_action(e:MouseEvent3D):void
		{
			if(meshListe[10].rotationX==0)	{O.stage.addEventListener(Event.ENTER_FRAME, openHood, false, 0, true);hideDoor(false)}
			else O.stage.addEventListener(Event.ENTER_FRAME, closeHood, false, 0, true);
		}
		//////////////////////////// DOORS
		public function door_right(e:MouseEvent3D):void
		{
			if(!Dright){	if(O.stage.hasEventListener(Event.ENTER_FRAME))O.stage.removeEventListener(Event.ENTER_FRAME, close_right)
				O.stage.addEventListener(Event.ENTER_FRAME, open_right, false, 0, true);hideDoor(false)}
			else {   	if(O.stage.hasEventListener(Event.ENTER_FRAME))O.stage.removeEventListener(Event.ENTER_FRAME, open_right)
				O.stage.addEventListener(Event.ENTER_FRAME, close_right, false, 0, true);
			}}
		public function door_left(e:MouseEvent3D):void
		{
			if(!Dleft){ if(O.stage.hasEventListener(Event.ENTER_FRAME))O.stage.removeEventListener(Event.ENTER_FRAME, close_left)
				O.stage.addEventListener(Event.ENTER_FRAME, open_left, false, 0, true);hideDoor(false)}
			else { 	if(O.stage.hasEventListener(Event.ENTER_FRAME))O.stage.removeEventListener(Event.ENTER_FRAME, open_left)
				O.stage.addEventListener(Event.ENTER_FRAME, close_left, false, 0, true);
			}}
		
		// DOORS
		private function open_right(e:Event):void
		{  
			Dright=true
			meshListe[8].rotationZ+=1; meshListe[8].rotationX+=.055; meshListe[8].rotationY-=.07;
			if(meshListe[8].rotationZ>=90){
				O.stage.removeEventListener(Event.ENTER_FRAME, open_right);
				meshListe[8].rotationZ=90;
				meshListe[8].rotationX=0;
			}
			meshListe[13].transform=meshListe[8].transform
		}
		private function close_right(e:Event):void
		{
			Dright=false
			meshListe[8].rotationZ-=1;  meshListe[8].rotationX-=.055; meshListe[8].rotationY+=.07;
			if(meshListe[8].rotationZ<=0){
				O.stage.removeEventListener(Event.ENTER_FRAME, close_right);
				meshListe[8].rotationZ=0;
				meshListe[8].rotationX=-5;
				//meshListe[8].rotationY=0;
			}
			meshListe[13].transform=meshListe[8].transform
		}
		private function open_left(e:Event):void
		{
			Dleft=true
			meshListe[7].rotationZ-=1;  meshListe[7].rotationX+=.055;  meshListe[7].rotationY+=.07;
			if(meshListe[7].rotationZ<=-90){
				O.stage.removeEventListener(Event.ENTER_FRAME, open_left); 
				meshListe[7].rotationZ=-90;
				meshListe[7].rotationX=0;
				//			meshListe[7].rotationY=5;
			}
			meshListe[14].transform=meshListe[7].transform
		}
		private function close_left(e:Event):void
		{
			Dleft=false
			meshListe[7].rotationZ+=1;  meshListe[7].rotationX-=.055; meshListe[7].rotationY-=.07;
			if(meshListe[7].rotationZ>=0){
				O.stage.removeEventListener(Event.ENTER_FRAME, close_left);
				meshListe[7].rotationZ=0; 
				meshListe[7].rotationX=-5; 
				//meshListe[7].rotationY=0; 
			}
			meshListe[14].transform=meshListe[7].transform
		}
		// HOOD
		private function openHood(e:Event):void
		{
			meshListe[10].rotationX+=1
			if(meshListe[10].rotationX>=70){
				O.stage.removeEventListener(Event.ENTER_FRAME, openHood); 
				meshListe[10].rotationX=70;
			}
		}
		private function closeHood(e:Event):void
		{
			meshListe[10].rotationX-=1
			if(meshListe[10].rotationX<=0){
				O.stage.removeEventListener(Event.ENTER_FRAME, closeHood); 
				meshListe[10].rotationX=0;
			}
		}
		// TRUNK
		private function openTrunk(e:Event):void
		{
			meshListe[12].rotationX-=1
			if(meshListe[12].rotationX<=-60){
				O.stage.removeEventListener(Event.ENTER_FRAME, openTrunk); 
				meshListe[12].rotationX=-60;
			}
		}
		private function closeTrunk(e:Event):void
		{
			meshListe[12].rotationX+=1
			if(meshListe[12].rotationX>=0){
				O.stage.removeEventListener(Event.ENTER_FRAME, closeTrunk); 
				meshListe[12].rotationX=0;
			}
		}
		private function followCar(e:Event):void
		{
			if(follow)follow=false
			else follow=true
		}
		
		//END
	}}